<?php

namespace App\Service\Kms\App;

use App\Http\Resources\Kms\App\ClientsListBackendResource;
use App\Http\Resources\Kms\App\ClientsListResource;
use App\Models\Common\ConfigModel;
use App\Models\Kms\App\ClientsAuthModel;
use App\Models\Kms\App\ClientsModel;
use App\Service\Kms\Common\FeishuService;
use App\Service\Kms\KmsBaseService;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use Laravel\Passport\ClientRepository;
use Laravel\Passport\Passport;

class ClientService extends KmsBaseService
{

    /**
     * @return array|void
     * @throws ValidationException
     */
    public static function list()
    {
        try {
            $version               = request()->header("version", "");
            $levelDepartments      = FeishuService::getDepartments()["levelDepartments"];
            $fsUserId              = auth()->user()->userId;
            $fsUserDepartment      = auth()->user()->departmentId;
            $fsUserLevelDepartment = $levelDepartments[$fsUserDepartment] ?? [];
            $clientsList           = ClientsModel::query()
                                                 ->where("status", ClientsModel::STATUS_NORMAL)
                                                 ->with([
                                                     "clientsAuthFsUser",
                                                     "clientsAuthFsDepartment",
                                                     "clientsVersionRel"
                                                 ])
                                                 ->orderByDesc("type")
                                                 ->orderBy("sort")
                                                 ->get()
                                                 ->filter(function (ClientsModel $clientsModel) use (
                                                     $version,
                                                     $fsUserId,
                                                     $fsUserLevelDepartment
                                                 ) {
                                                     if (
                                                         $clientsModel->type == ClientsModel::TYPE_SELF
                                                         &&
                                                         $clientsModel->releaseVersion
                                                         &&
                                                         version_compare($version, $clientsModel->releaseVersion, "<")
                                                     ) {
                                                         return false;
                                                     }

                                                     if ($clientsModel->authType == ClientsModel::AUTH_TYPE_ALL) {
                                                         return true;
                                                     }

                                                     if (
                                                         $clientsModel->clientsAuthFsUser
                                                         &&
                                                         $clientsModel->clientsAuthFsUser->where("targetId", $fsUserId)
                                                                                         ->count() > 0) {
                                                         return true;
                                                     }
                                                     if (
                                                         $clientsModel->clientsAuthFsDepartment
                                                         &&
                                                         $clientsModel->clientsAuthFsUser->whereIn("targetId",
                                                             $fsUserLevelDepartment)->count() > 0) {
                                                         return true;
                                                     }
                                                     return false;
                                                 });


            return [
                "list" => ClientsListResource::collection($clientsList)
            ];

        } catch (\Exception $exception) {
            handleException($exception, null, null, "获取自建应用列表失败");
        }
    }

    /**
     * @return array|void
     * @throws ValidationException
     */
    public static function myList()
    {
        try {
            $version               = request()->header("version", "");
            $levelDepartments      = FeishuService::getDepartments()["levelDepartments"];
            $fsUserId              = auth()->user()->userId;
            $fsUserDepartment      = auth()->user()->departmentId;
            $fsUserLevelDepartment = $levelDepartments[$fsUserDepartment] ?? [];
            $clientsList           = ClientsModel::query()
                                                 ->where("status", ClientsModel::STATUS_NORMAL)
                                                 ->with([
                                                     "clientsAuthFsUser",
                                                     "clientsAuthFsDepartment",
                                                     "clientsVersionRel"
                                                 ])
                                                 ->orderByDesc("type")
                                                 ->orderBy("sort")
                                                 ->get()
                                                 ->filter(function (ClientsModel $clientsModel) use (
                                                     $version,
                                                     $fsUserId,
                                                     $fsUserLevelDepartment
                                                 ) {
                                                     if (
                                                         $clientsModel->type == ClientsModel::TYPE_SELF
                                                         &&
                                                         $clientsModel->releaseVersion
                                                         &&
                                                         version_compare($version, $clientsModel->releaseVersion, "<")
                                                     ) {
                                                         return false;
                                                     }

                                                     if ($clientsModel->authType == ClientsModel::AUTH_TYPE_ALL) {
                                                         return true;
                                                     }

                                                     if (
                                                         $clientsModel->clientsAuthFsUser
                                                         &&
                                                         $clientsModel->clientsAuthFsUser->where("targetId", $fsUserId)
                                                                                         ->count() > 0) {
                                                         return true;
                                                     }
                                                     if (
                                                         $clientsModel->clientsAuthFsDepartment
                                                         &&
                                                         $clientsModel->clientsAuthFsUser->whereIn("targetId",
                                                             $fsUserLevelDepartment)->count() > 0) {
                                                         return true;
                                                     }
                                                     return false;
                                                 });


            $name = 'appMyList';
            if (!isProd() && !isTest()) {
                // PRE 环境
                $name = 'appMyList.pre';
            }
            $configList = ConfigModel::getValueNewJson('kms', $name);

            foreach ($configList as &$oneConfig) {
                foreach ($oneConfig['children'] as $key => &$item) {
                    $clientOne = $clientsList->where('id', $item['id'])->first();
                    $orgItem   = $item;

                    if (empty($clientOne)) {
                        unset($oneConfig['children'][$key]);
                        continue;
                    }
                    $item = ClientsListResource::formatData($clientOne);

                    foreach ($orgItem as $orgItemKey => $value) {
                        $item[$orgItemKey] = $value;
                    }

                }
                $oneConfig['children'] = array_values($oneConfig['children']);
            }

            return [
                "list" => $configList
            ];

        } catch (\Exception $exception) {
            handleException($exception, null, null, "获取自建应用列表失败");
        }
    }

    /**
     * @param object $params
     * @return array
     */
    public static function backendList(object $params): array
    {
        $pageSize = attributeGet($params, "pageSize", 10);
        $page     = attributeGet($params, "pageNum", 1);
        $paginate = ClientsModel::query()
                                ->with([
                                    "clientsAuthFsUser"       => function ($query) {
                                        $query->where("type", ClientsAuthModel::TYPE_FS_USER)
                                              ->with("fsUserRel", function ($query) {
                                                  $query->select(["id", "userId", "rmsUserId", "name", "nickname"]);
                                              })->select(["clientId", "type", "targetId"]);
                                    },
                                    "clientsAuthFsDepartment" => function ($query) {
                                        $query->where("type", ClientsAuthModel::TYPE_FS_DEPARTMENT)
                                              ->with("fsDepartmentRel", function ($query) {
                                                  $query->select(["openDepartmentId", "name"]);
                                              })->select(["clientId", "type", "targetId"]);
                                    },
                                    "clientsVersionRel"
                                ])
                                ->where("isDeleted", 0)
                                ->orderByDesc("type")
                                ->orderBy("sort")
                                ->select([
                                    "id",
                                    "icon",
                                    "name",
                                    "desc",
                                    "sort",
                                    "type",
                                    "childType",
                                    "authType",
                                    "clientId",
                                    "uniAppId",
                                    "versionId",
                                    "status"
                                ])
                                ->paginate($pageSize, ["*"], "pageNum", $page);

        return [
            "count"    => $paginate->total(),
            "pageNum"  => $page,
            "pageSize" => $pageSize,
            "list"     => ClientsListBackendResource::collection($paginate->items())
        ];
    }

    /**
     * @param object $params
     */
    public static function addClient(object $params)
    {
        try {
            DB::beginTransaction();

            $clientId = ClientsModel::query()->insertGetId([
                "icon"         => $params->icon,
                "name"         => $params->name,
                "desc"         => $params->desc,
                "authType"     => $params->authType,
                "uniAppId"     => $params->uniAppId,
                "sort"         => $params->sort,
                "status"       => ClientsModel::STATUS_NORMAL,
                "createdByUid" => request()->user()->id,
                "updatedByUid" => request()->user()->id,
                "createdAt"    => time(),
                "updatedAt"    => time()
            ]);

            if ($params->authType == ClientsModel::AUTH_TYPE_PART) {
                $authInsert = [];
                if (!empty($params->authUser)) {
                    collect($params->authUser)->each(function ($targetId) use (&$authInsert, $clientId) {
                        array_push($authInsert, [
                            "clientId"     => $clientId,
                            "type"         => ClientsAuthModel::TYPE_FS_USER,
                            "targetId"     => $targetId,
                            "createdByUid" => request()->user()->id,
                            "updatedByUid" => request()->user()->id,
                            "createdAt"    => time(),
                            "updatedAt"    => time()
                        ]);
                    });
                }

                if (!empty($params->authDepartment)) {
                    collect($params->authDepartment)->each(function ($targetId) use (&$authInsert, $clientId) {
                        array_push($authInsert, [
                            "clientId"     => $clientId,
                            "type"         => ClientsAuthModel::TYPE_FS_DEPARTMENT,
                            "targetId"     => $targetId,
                            "createdByUid" => request()->user()->id,
                            "updatedByUid" => request()->user()->id,
                            "createdAt"    => time(),
                            "updatedAt"    => time()
                        ]);
                    });
                }

                ClientsAuthModel::query()->insert($authInsert);
            }

            $authClient = (new ClientRepository())->create(
                null, $clientId, "", null, false, false, true
            );

            ClientsModel::query()->where("id", $clientId)->update(["clientId" => $authClient->id]);
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            handleKfException($exception);
        }
    }

    /**
     * @param object $params
     */
    public static function updateClient(object $params)
    {
        try {
            DB::beginTransaction();

            $params->nowTime = time();
            ClientsModel::query()->where("id", $params->id)->update([
                "icon"         => $params->icon,
                "name"         => $params->name,
                "desc"         => $params->desc,
                "authType"     => $params->authType,
                "uniAppId"     => $params->uniAppId,
                "sort"         => $params->sort,
                "updatedAt"    => $params->nowTime,
                "updatedByUid" => request()->user()->id,
            ]);

            ClientsAuthModel::query()->where("clientId", $params->id)->update([
                "isDeleted"    => 1,
                "updatedAt"    => $params->nowTime,
                "updatedByUid" => request()->user()->id,
            ]);

            if ($params->authType == ClientsModel::AUTH_TYPE_PART) {
                $authInsert = [];
                if (!empty($params->authUser)) {
                    collect($params->authUser)->each(function ($targetId) use (&$authInsert, $params) {
                        array_push($authInsert, [
                            "clientId"     => $params->id,
                            "type"         => ClientsAuthModel::TYPE_FS_USER,
                            "targetId"     => $targetId,
                            "createdAt"    => $params->nowTime,
                            "updatedAt"    => $params->nowTime,
                            "createdByUid" => request()->user()->id,
                            "updatedByUid" => request()->user()->id,
                        ]);
                    });
                }

                if (!empty($params->authDepartment)) {
                    collect($params->authDepartment)->each(function ($targetId) use (&$authInsert, $params) {
                        array_push($authInsert, [
                            "clientId"     => $params->id,
                            "type"         => ClientsAuthModel::TYPE_FS_DEPARTMENT,
                            "targetId"     => $targetId,
                            "createdAt"    => $params->nowTime,
                            "updatedAt"    => $params->nowTime,
                            "createdByUid" => request()->user()->id,
                            "updatedByUid" => request()->user()->id,
                        ]);
                    });
                }

                ClientsAuthModel::query()->insert($authInsert);
            }

            if (ClientsModel::query()->where("id", $params->id)->first()->clientId <= 0) {
                $authClient = (new ClientRepository())->create(
                    null, $params->id, "", null, false, false, true
                );

                ClientsModel::query()->where("id", $params->id)->update(["clientId" => $authClient->id]);
            }
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            handleKfException($exception);
        }
    }


    /**
     * @return void
     */
    public static function statusClient(object $params)
    {
        try {

            ClientsModel::query()->where("id", $params->id)->update([
                "status"       => $params->status,
                "createdByUid" => request()->user()->id,
                "updatedAt"    => time()
            ]);

        } catch (\Exception $exception) {
            handleKfException($exception);
        }
    }

    /**
     * @return void
     */
    public static function deleteClient(object $params)
    {
        try {
            DB::beginTransaction();
            ClientsModel::query()->where("id", $params->id)->update([
                "isDeleted" => 1,
                "updatedAt" => time()
            ]);

            Passport::clientModel()::query()->where("name", $params->id)->update(["revoked" => 1]);
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            handleKfException($exception);
        }
    }
}
